#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "lib.h"
#include "endian.h"


enum _action
{
	ACT_NONE,
	ACT_WORD,
	ACT_PADDING
};


void
endian(void *Data, char *Format, uint32 Alignment)
{
	char *		fmt		= Format;
	uint8 *		data	= (uint8 *)Data;
	uint32		align	= Alignment;
	uint32		action;
	uint32		amount;
	uint32		diff;
	uint32		low, high;
	uint8 *		swap;


	// Extract special format directives...
	if (strchr(fmt, ':'))
	{
		while (*fmt != ':')
		{
			fmt++;
		}

		// Advance past ':'
		fmt++;
	}

	while (*fmt)
	{
		action = ACT_NONE;

		switch (*fmt++)
		{
			case 'w': case 'W':
				action = ACT_WORD;
				break;
			case 'p': case 'P':
				action = ACT_PADDING;
			default:
				break;
		}

		if (sscanf(fmt, "%u", &amount) == 0)
		{
			DEBUGMSG(("Improper format string!\n"));
		}

		while (isdigit(*fmt))
			fmt++;

		if (action == ACT_PADDING)
		{
			data += amount;
		}

		if (action == ACT_WORD)
		{
			// Alignment adjust...
			if ((diff = ((uint32)data - (uint32)Data) % align) != 0)
				data += align - diff;

			low = 0;
			high = amount - 1;
			swap = data;

			// xor swap...("safe", generic, & flexible)
			while (low < high)
				swap[low] ^= swap[high] ^= swap[low++] ^= swap[high--];

			data += amount;
		}
	}
}
